use std::{collections::HashMap, sync::Arc};

use monitor::{CompleterSuggestion, Monitor, MonitorCommand};

use crate::{inode::link_path_walk, DfsResult};

struct PwdCommand;

impl PwdCommand {
    fn do_pwd_p(&self) -> String {
        let mut pwd = do_pwd();
        if pwd.len() > 1 && pwd.ends_with('/') {
            pwd.pop();
        }
        pwd
    }
}

impl MonitorCommand for PwdCommand {
    fn mon_protocol_exec(&self, _: &monitor::Protocol) -> DfsResult<monitor::Protocol> {
        let pwd = self.do_pwd_p();
        let mut hash = HashMap::new();
        hash.insert("pwd".to_string(), pwd);
        Ok(hash)
    }

    fn mon_readline_arg_type(&self) -> Option<&'static str> {
        Some("")
    }

    fn mon_readline_completer(&self, _: &[&str], _: bool) -> Option<CompleterSuggestion> {
        None
    }

    fn mon_readline_exec(
        &self,
        _: &HashMap<String, String>,
        printer: &monitor::MonitorPrinter,
    ) -> DfsResult<()> {
        let pwd = self.do_pwd_p();
        printer.print(pwd);
        Ok(())
    }

    fn mon_readline_help(&self) -> String {
        String::from("打印当前工作目录的名字")
    }

    fn mon_readline_long_help(&self) -> Option<String> {
        None
    }
}

pub(crate) fn do_pwd() -> String {
    let mut inode = link_path_walk(".").unwrap();

    let mut v = Vec::new();
    loop {
        v.push(inode.name().clone());
        let parent = inode.parent();
        if parent.is_none() {
            break;
        }
        inode = parent.unwrap();
    }

    let mut pwd = String::new();
    for i in v.iter().rev() {
        pwd.push_str(i);
        if i.as_str() != "/" {
            pwd.push('/');
        }
    }

    pwd
}

pub(crate) fn monitor_command_pwd_register(mon: &Monitor) {
    mon.register_command("pwd", Arc::new(PwdCommand)).unwrap();
}
